home *** CD-ROM | disk | FTP | other *** search
/ By Popular Request 2.0 / By Popular Request 2.0 (Arsenal Computer).ISO / amiga_6 / xprz351s.lha / Send.c < prev    next >
C/C++ Source or Header  |  1995-01-03  |  24KB  |  787 lines

  1. /**********************************************************************
  2.  * Send.c: File transmission routines for xprzmodem.library;
  3.  * Original Version 2.10, 12 February 1991, by Rick Huebner.
  4.  * Based closely on Chuck Forsberg's sz.c example ZModem code,
  5.  * but too pervasively modified to even think of detailing the changes.
  6.  * Released to the Public Domain; do as you like with this code.
  7.  *
  8.  * Version 2.50, 15 November 1991, CRC-32 additions by William M. Perkins.
  9.  * Version 2.51 29, January 1992, RX_timout fix by John Tillema
  10.  * Version 2.52   6 March 1992, Very minor fix with compiled 020 library
  11.  *               by William M. Perkins.
  12.  * Version 2.63, 30 July 1993 build in locale, by Rainer Hess
  13.  * Version 3.1,  17 August 1993, added Auto-Blocksize by Rainer Hess
  14.  * Version 3.2,  10 Nov 1994, restored FTN Support by Robert Williamson
  15.  *
  16.  **********************************************************************/
  17.  
  18. #include "xprzmodem_all.h"
  19.  
  20. #define CATCOMP_NUMBERS
  21. #include "xprzmodem_catalog.h"
  22.  
  23. #ifdef DEBUGLOG
  24. extern void *DebugLog;
  25. #endif
  26.  
  27. /**********************************************************
  28.  *      long XProtocolSend(struct XPR_IO *xio)
  29.  *
  30.  * Main file transmission routine; called by comm program
  31.  **********************************************************/
  32. long __saveds __asm 
  33. XProtocolSend (register __a0 struct XPR_IO *xio)
  34. {
  35.   struct Vars *v;
  36.   short err;
  37.  
  38.   /* Perform common setup and initializations */
  39.   if (!(v = setup (xio)))
  40.     return XPRS_FAILURE;
  41.  
  42.   v->Rxtimeout = v->FTNmode ? 600 : 300;
  43.   v->Wantfcs32 = TRUE;
  44.   v->Rxflags = 0;
  45.  
  46.   /* first flush the inbound buffer */
  47.   if (v->FTNmode && v->io.xpr_sflush)
  48.   {
  49. #ifdef KDEBUG 
  50. KPrintF("Flushing\n");  
  51. #endif  
  52.         (*v->io.xpr_sflush) ();
  53.   }
  54.  
  55. #ifdef KDEBUG
  56. KPrintF("\nXProtocolSend\n");
  57. KPrintF("XprBaud:%ld  UserBaud:%ld\n",v->Baud,v->NewBaud);
  58. KPrintF("FtnMode:%s   DirectZap:%s   Nofiles:%s   SmallBlocks:%s\n",
  59.   (v->FTNmode ? "TRUE" : "FALSE"),
  60.   (v->dzap ? "TRUE" : "FALSE"),
  61.   (v->NoFiles ? "TRUE" : "FALSE"),
  62.   (v->SmallBlocks ? "TRUE" : "FALSE"));
  63. KPrintF("Rxtimeout:%ld\n",v->Rxtimeout);
  64. KPrintF("Filebufmax:%ld   Tframlen:%ld  Ksize:%ld\n", v->Filebufmax,v->Tframlen,v->Ksize);
  65. KPrintF("Pktbuf:%ld   Modembuf:%ld  Outbuf:%ld\n",sizeof(v->Pktbuf),sizeof(v->Modembuf),sizeof(v->Outbuf));
  66. #endif
  67.  
  68.   /* Transfer the files */
  69.   zmputs (v, "rz\r");
  70.   stohdr (v, 0L);
  71.   zshhdr (v, ZRQINIT);
  72.   sendbuf (v);
  73.   if (getzrxinit (v) == ERROR)
  74.     upderr (v, GetLocalString( &li, MSG_UPLOAD_USER_ERROR ), XPRU_UPLOAD);
  75.   else
  76.     sendbatch (v);
  77.  
  78.   /* Clean up and return */
  79.   if (err = v->Errcnt)
  80.     upderr (v, GetLocalString( &li, MSG_SKIPPED_DUE_TO_ERRORS ), XPRU_UPLOAD);
  81.   else
  82.     updmsg (v, GetLocalString( &li, MSG_SEND_DONE ), XPRU_UPLOAD);
  83.  
  84.   if (v->io.xpr_setserial && v->Oldstatus != -1)
  85.     (*v->io.xpr_setserial) (v->Oldstatus);
  86.   FreeMem (v->Filebuf, v->Filebufmax);
  87.   FreeMem (v, (long) sizeof (struct Vars));
  88.  
  89. #ifdef DEBUGLOG
  90.   if (DebugLog)
  91.     {
  92.       (*v->io.xpr_fclose) ((long) DebugLog);
  93.       DebugLog = NULL;
  94.     }
  95. #endif
  96. #ifdef KDEBUG
  97. KPrintF("XProtcolSend returning:%s\n",err ? "XPRS_FAILURE" : "XPRS_SUCCESS");
  98. #endif
  99.   return (err) ? XPRS_FAILURE : XPRS_SUCCESS;
  100. } /* End of long XProtocolSend() */
  101.  
  102. /**********************************************************
  103.  *      short getzrxinit(struct Vars *v)
  104.  *
  105.  * Negotiate with receiver to start a file transfer
  106.  **********************************************************/
  107. short
  108. getzrxinit (struct Vars *v)
  109. {
  110.   short n;
  111.  
  112.   for (n = v->ErrorLimit; --n >= 0;)
  113.     {
  114.       /* Check for abort from comm program */
  115.       if (v->io.xpr_chkabort && (*v->io.xpr_chkabort) ())
  116.         return ERROR;
  117.       switch (zgethdr (v))
  118.       {
  119.         case ZCHALLENGE:        /* Echo receiver's challenge number */
  120.           stohdr (v, v->Rxpos);
  121.           zshhdr (v, ZACK);
  122.           sendbuf (v);
  123.           continue;
  124.         case ZCOMMAND:                /* They didn't see our ZRQINIT; try again */
  125.           stohdr (v, 0L);
  126.           zshhdr (v, ZRQINIT);
  127.           sendbuf (v);
  128.           continue;
  129.         case ZRINIT:                /* Receiver ready; get transfer parameters */
  130.           v->Rxflags = 0xFF & v->Rxhdr[ZF0];
  131.           v->Txfcs32 = (v->Wantfcs32 && (v->Rxflags & CANFC32));
  132.           v->Rxbuflen = ((USHORT) v->Rxhdr[ZP1] << 8) | v->Rxhdr[ZP0];
  133. #ifdef DEBUGLOG
  134.           xprsprintf (v->Msgbuf, "Txfcs32=%ld Rxbuflen=%ld Tframlen=%ld\n",
  135.                  (long) v->Txfcs32, (long) v->Rxbuflen, (long) v->Tframlen);
  136.           dlog (v, v->Msgbuf);
  137.           D (DEBUGINFO);
  138. #endif
  139. #ifdef KDEBUG
  140. KPrintF("ZRINIT: Txfcs32=%ld Rxbuflen=%ld Tframlen=%ld Ksize=%ld\n",
  141.          (long) v->Txfcs32, (long) v->Rxbuflen, (long) v->Tframlen, (long) v->Ksize );
  142. #endif
  143.           /* Use shortest of the two side's max frame lengths */
  144.           if (v->Tframlen && (!v->Rxbuflen || v->Tframlen < v->Rxbuflen))
  145.             v->Rxbuflen = v->Tframlen;
  146. #ifdef DEBUGLOG
  147.           xprsprintf (v->Msgbuf, "Rxbuflen=%ld\n", (long) v->Rxbuflen);
  148.           dlog (v, v->Msgbuf);
  149.           D (DEBUGINFO);
  150. #endif
  151. #ifdef KDEBUG
  152. KPrintF("Adjusted Rxbuflen=%ld Tframlen=%ld\n", (long) v->Rxbuflen, (long) v->Tframlen);
  153. #endif
  154.           return OK;
  155.         case ZCAN:
  156.         case RCDO:
  157.         case TIMEOUT:
  158.           upderr (v, v->Msgbuf, XPRU_UPLOAD);
  159.           return ERROR;
  160.         case ZRQINIT:
  161.           if (v->Rxhdr[ZF0] == ZCOMMAND)
  162.             continue;
  163.           /* fallthrough... */
  164.         default:
  165.           zshhdr (v, ZNAK);
  166.           sendbuf (v);
  167.           continue;
  168.         }
  169.     }
  170.   return ERROR;
  171. }                                /* End of short getzrxinit() */
  172.  
  173. /**********************************************************
  174.  *      void sendbatch(struct Vars *v)
  175.  *
  176.  * Send a batch of files
  177.  **********************************************************/
  178. void
  179. sendbatch (struct Vars *v)
  180. {
  181.   UBYTE single, done = FALSE;
  182.   long fstate;
  183.  
  184. #ifdef DEBUGLOG
  185.   D (DEBUGINFO);
  186. #endif
  187.  
  188.    /* Lets just clear this in case the host program fails to set this */
  189.    v->Filcnt = 0; /* Up to now we have not sent any files */
  190.  
  191.   /* If template routines not provided, must be single filename */
  192.   if (!v->io.xpr_ffirst || !v->io.xpr_fnext)
  193.   {
  194.     single = TRUE;
  195.     strcpy (v->Filename, v->io.xpr_filename);
  196.     if(!(v->Filename[0]))
  197.     {
  198.       if (v->NoFiles)
  199.         updmsg(v, GetLocalString( &li, MSG_NO_FILES_REQUIRED ), XPRU_UPLOAD);
  200.       else
  201.         upderr(v, GetLocalString( &li, MSG_NO_FILES_SPECIFIED ), XPRU_UPLOAD);
  202.       done = TRUE;
  203.     }
  204.     /* Else use the template routines to get the first filename */
  205.   }
  206.   else
  207.   {
  208.     single = FALSE;
  209.     fstate = (*v->io.xpr_ffirst) (v->Filename, v->io.xpr_filename);
  210.     if (!fstate || !(v->Filename[0]))  /* There are no files found */
  211.     {
  212.       if (v->NoFiles) /* that's OK, we allow this kind of thing */
  213.       {  
  214.         updmsg(v, GetLocalString( &li, MSG_NO_FILES_REQUIRED ), XPRU_UPLOAD);
  215.         done = TRUE;
  216.       }
  217.       else
  218.       {  /* In that case, I'm leaving */
  219.         if((!(v->io.xpr_filename) || !(v->io.xpr_filename[0]))) upderr(v,GetLocalString( &li, MSG_NO_FILES_SPECIFIED ), XPRU_UPLOAD);
  220.           else upderr (v, GetLocalString( &li, MSG_NO_FILES_MATCH_TEMPLATE ), XPRU_UPLOAD);
  221.         return;
  222.       }
  223.     }
  224.   }
  225.  
  226.   /* If using templates, keep getting names & sending until done */
  227.   while (!done)
  228.   {
  229.     if (sendone (v) == ERROR)
  230.       return;
  231.     if (single)
  232.       break;
  233.     fstate = (*v->io.xpr_fnext) (fstate, v->Filename, v->io.xpr_filename);
  234.     done = !fstate;
  235.   }
  236.  
  237.   /* End batch and return; if we never got started, just cancel receiver */
  238.   if (v->Filcnt || v->NoFiles)
  239.     saybibi (v);
  240.   else
  241.     canit (v);
  242. }                                /* End of void sendbatch() */
  243.  
  244. /**********************************************************
  245.  *      short sendone(struct Vars *v)
  246.  *
  247.  * Send the file named in v->Filename
  248.  **********************************************************/
  249. short 
  250. sendone (struct Vars *v)
  251. {
  252.   struct SetupVars *sv;
  253.  
  254. #ifdef DEBUGLOG
  255.   xprsprintf (v->Msgbuf, "*** Sending %s\n", v->Filename);
  256.   dlog (v, v->Msgbuf);
  257.   D (DEBUGINFO);
  258. #endif
  259.  
  260.   /* Display name of file being sent for user */
  261.   if (v->NoMask) v->xpru.xpru_updatemask = XPRU_FILENAME;
  262.   else v->xpru.xpru_updatemask = XPRU_UPLOAD | XPRU_FILENAME;
  263.   v->xpru.xpru_filename = v->Filename;
  264.   (*v->io.xpr_update) (&v->xpru);
  265.  
  266.   /* Set text/binary mode according to options before opening file */
  267.   set_textmode (v);
  268.  
  269.   /* Open the file, if possible */
  270.   if (!(v->File = bfopen (v, "r")))
  271.   {
  272.     ++v->Errcnt;
  273.     upderr (v, GetLocalString( &li, MSG_CANT_OPEN_FILE ), XPRU_UPLOAD);
  274.     return OK;                /* pass over it, there may be others */
  275.   }
  276.   ++v->Filcnt;
  277.   getsystime (&v->Starttime);
  278.  
  279.   /* Kick off the file transfer */
  280.   sv = (void *) v->io.xpr_data;
  281.   switch (sendname (v))
  282.   {
  283.   case ERROR:
  284.     ++v->Errcnt;
  285.     return ERROR;
  286.   case OK:
  287.     bfclose (v);
  288.     /* File sent; if option DY, delete file after sending */
  289.     if (*sv->option_d == 'Y' && v->io.xpr_extension >= 2 && v->io.xpr_unlink)
  290.     {
  291.       updmsg (v, GetLocalString( &li, MSG_DELETING_FILE_AFTER_SEND ), XPRU_UPLOAD);
  292.       (*v->io.xpr_unlink) (v->Filename);
  293.     }
  294.     break;
  295.   }
  296.   return OK;
  297. }                                /* End of short sendone() */
  298.  
  299. /**********************************************************
  300.  *      short sendname(struct Vars *v)
  301.  *
  302.  * Build file info block consisting of file name, length,
  303.  * time, and mode
  304.  **********************************************************/
  305. short
  306. sendname (struct Vars *v)
  307. {
  308.   struct SetupVars *sv;
  309.   UBYTE *p, *q, buff[32];
  310.  
  311. #ifdef DEBUGLOG
  312.   D (DEBUGINFO);
  313. #endif
  314.  
  315.   /* Initialize comm program transfer status display */
  316.   v->Fsize = (v->io.xpr_finfo) ? (*v->io.xpr_finfo) (v->Filename, 1L) : -1;
  317.   if (v->NoMask) 
  318.     v->xpru.xpru_updatemask = XPRU_PROTOCOL | XPRU_FILESIZE | XPRU_MSG
  319.       | XPRU_BLOCKS | XPRU_ERRORS | XPRU_TIMEOUTS | XPRU_BLOCKCHECK
  320.       | XPRU_BYTES | XPRU_EXPECTTIME | XPRU_ELAPSEDTIME | XPRU_DATARATE | XPRU_BLOCKSIZE;
  321.   else
  322.     v->xpru.xpru_updatemask = XPRU_UPLOAD | XPRU_PROTOCOL | XPRU_FILESIZE | XPRU_MSG
  323.       | XPRU_BLOCKS | XPRU_ERRORS | XPRU_TIMEOUTS | XPRU_BLOCKCHECK
  324.       | XPRU_BYTES | XPRU_EXPECTTIME | XPRU_ELAPSEDTIME | XPRU_DATARATE | XPRU_BLOCKSIZE;
  325.  
  326.   if (v->SmallBlocks || (v->Ksize == 1024))
  327.     v->xpru.xpru_protocol = (v->FTNmode) ? "ZedZip" : "Zmodem";
  328.   else 
  329.     v->xpru.xpru_protocol = (v->FTNmode) ? "ZedZap" : "SZmodem";
  330.  
  331.   if (v->dzap)
  332.     v->xpru.xpru_protocol = "DirectZap";
  333.  
  334.   v->xpru.xpru_filesize = v->Fsize;
  335.   v->xpru.xpru_msg = (v->Lzconv == ZCNL) ? GetLocalString( &li, MSG_SENDING_TEXT_FILE ) :
  336.     ((v->Lzconv == ZCBIN) ? GetLocalString( &li, MSG_SENDING_BINARY_FILE ) : GetLocalString( &li, MSG_SENDING_FILE ));
  337.   v->xpru.xpru_blocks = v->xpru.xpru_errors = v->xpru.xpru_timeouts = 0;
  338.   v->xpru.xpru_blockcheck = v->Crc32t ? "CRC-32" : "CRC-16";
  339.   v->xpru.xpru_bytes = v->Strtpos = 0;
  340.   v->xpru.xpru_blocksize = v->Ksize;
  341.   update_rate (v);
  342.   (*v->io.xpr_update) (&v->xpru);
  343.  
  344. #ifdef KDEBUG
  345. KPrintF("Protocol:%s    FileName:%s   FileSize:%ld\n",v->xpru.xpru_protocol,v->Filename,v->Fsize);
  346. #endif
  347.  
  348.   sv = (void *) v->io.xpr_data;
  349.   if (*sv->option_s == 'Y')
  350.   {
  351.     /* If "SY" option selected, send full path */
  352.     strcpy (v->Pktbuf, v->Filename);
  353.     p = v->Pktbuf + strlen (v->Pktbuf) + 1;
  354.   }
  355.   else
  356.   {
  357.     /* else extract outgoing file name without directory path */
  358.     for (p = v->Filename, q = v->Pktbuf; *p; ++p, ++q)
  359.       if ((*q = *p) == '/' || *q == ':')
  360.         q = v->Pktbuf - 1;
  361.     *q = '\0';
  362.     p = ++q;
  363.   }
  364.  
  365.   /* Zero out remainder of file info packet */
  366.   memset (p, 0, sizeof (v->Pktbuf) - (p - v->Pktbuf));
  367.  
  368.   /* Store file size, timestamp, and mode in info packet */
  369.   /*
  370.      * XPR spec doesn't provide a way to get the file timestamp or file mode,
  371.      * so we'll just fake it with the current time and a dummy 0.
  372.    */
  373.   stcl_o (buff, getsystime (NULL) + UnixTimeOffset);
  374.   /* amiga.lib sprintf() can't do %lo format, so we do it the hard way */
  375.   /* Yes, octal; ZModem was originally done on Unix, and they like octal there */
  376.   xprsprintf (p, "%ld %s 0", (v->Fsize < 0) ? 0L : v->Fsize, buff);
  377.  
  378.   /* Send filename packet */
  379.   return zsendfile (v, (short) (p - v->Pktbuf + strlen (p) + 1));
  380. }                                /* End of short sendname() */
  381.  
  382. /**********************************************************
  383.  *      short zsendfile(struct Vars *v, short blen)
  384.  *
  385.  * Send the filename packet and see if receiver will accept
  386.  * file
  387.  **********************************************************/
  388. short
  389. zsendfile (struct Vars *v, short blen)
  390. {
  391.   short c;
  392.  
  393. #ifdef DEBUGLOG
  394.   D (DEBUGINFO);
  395. #endif
  396.  
  397.   while (TRUE)
  398.   {
  399.     v->Txhdr[ZF0] = v->Lzconv;      /* Text or Binary mode; from config string */
  400.     v->Txhdr[ZF1] = LZMANAG;        /* Default file management mode */
  401.     v->Txhdr[ZF2] = LZTRANS;        /* Default file transport mode */
  402.     v->Txhdr[ZF3] = 0;
  403.     zsbhdr (v, ZFILE);
  404.     zsdata (v, blen, ZCRCW);
  405.     sendbuf (v);
  406.   again:
  407.     /* Check for abort from comm program */
  408.     if (v->io.xpr_chkabort && (*v->io.xpr_chkabort) ())
  409.     {
  410.       bfclose (v);
  411.       return ERROR;
  412.     }
  413.     switch (c = zgethdr (v))
  414.     {
  415.     case ZRINIT:
  416.       goto again;
  417.     case ZCAN:
  418.     case ZCRC:
  419.     case RCDO:
  420.     case TIMEOUT:
  421.     case ZABORT:
  422.     case ZFIN:
  423.       upderr (v, v->Msgbuf, XPRU_UPLOAD);
  424.       return ERROR;
  425.     case ZSKIP:                /* Receiver doesn't want this one */
  426.       upderr (v, GetLocalString( &li, MSG_SKIP_COMMAND_RECEIVED ), XPRU_UPLOAD);
  427.       bfclose (v);
  428.       return c;
  429.     case ZRPOS:                /* Receiver wants it; this is starting position */
  430.       bfseek (v, v->Rxpos);
  431.       v->Strtpos = v->Txpos = v->Rxpos;
  432.       if (v->Strtpos != 0)
  433.         updmsg (v, GetLocalString( &li, MSG_RESUMING_SEND ), XPRU_UPLOAD);
  434.       if (v->io.xpr_sflush)
  435.         (*v->io.xpr_sflush) ();
  436.       v->Modemcount = 0;
  437. #ifdef KDEBUG
  438. KPrintF("zgethdr starting ZRPOS: Strtpos=%ld Rxpos=%ld Txpos=%ld\n", (long) v->Strtpos, (long) v->Rxpos, (long) v->Txpos);
  439. #endif
  440.       return zsendfdata (v);
  441.     }
  442.   }
  443. }                                /* End of short zsendfile() */
  444.  
  445. /**********************************************************
  446.  *      short zsendfdata(struct Vars *v)
  447.  *
  448.  * Send the file data
  449.  **********************************************************/
  450. short
  451. zsendfdata (struct Vars *v)
  452. {
  453.   short c, e, blklen, goodbytes = 0;
  454.   USHORT framelen, maxblklen, goodneeded = 512;
  455.  
  456. #ifdef DEBUGLOG
  457.   D (DEBUGINFO);
  458. #endif
  459.  
  460.   /* Figure out max data packet size to send */
  461.   if (v->FTNmode)     
  462.   {   
  463.     maxblklen = 
  464.       (short) ((v->NewBaud == 0) ? (v->Baud * 8192/9600) : (v->NewBaud * 8192/9600));
  465.  
  466.     if (v->Ksize < maxblklen)
  467.       maxblklen = v->Ksize;   
  468.     if (v->Rxbuflen && (maxblklen > v->Rxbuflen))
  469.       maxblklen = v->Rxbuflen;    
  470.     blklen = maxblklen;   
  471. #ifdef KDEBUG
  472. KPrintF("FTNmode blocks\n");
  473. #endif
  474.   }   
  475.   else /* not ftn mode */ 
  476.   { 
  477.     maxblklen = v->Ksize;
  478.     if (v->Rxbuflen && maxblklen > v->Rxbuflen)
  479.       maxblklen = v->Rxbuflen;
  480.     blklen = (v->NewBaud == 0) ? ((v->Baud < 1200) ? 256 : v->Ksize) : ((v->NewBaud < 1200) ? 256 : v->Ksize);
  481.     if (blklen > maxblklen)
  482.       blklen = maxblklen;
  483.   }   
  484. #ifdef DEBUGLOG
  485.   xprsprintf (v->Msgbuf, "Rxbuflen=%ld blklen=%ld\n",
  486.      (long) v->Rxbuflen, (long) blklen);
  487.   dlog (v, v->Msgbuf);
  488.   D (DEBUGINFO);
  489. #endif
  490. #ifdef KDEBUG
  491. KPrintF("Rxbuflen=%ld  maxblklen=%ld  blklen=%ld\n",
  492.     (long) v->Rxbuflen, (long) maxblklen, (long) blklen);
  493. #endif
  494.  
  495.   /* If an interruption happened, handle it; else keep sending data */
  496. somemore:
  497.   while (char_avail (v))
  498.   {
  499.     /* Check for another incoming packet while discarding line noise */
  500.     switch (readock (v, 1))
  501.     {
  502.       case CAN:
  503.       case RCDO:
  504.       case ZPAD:
  505.         break;
  506.       default:
  507.         continue;
  508.     }
  509.   waitack:
  510. #ifdef DEBUGLOG
  511.     dlog (v, "--- At waitack\n");
  512.     D (DEBUGINFO);
  513. #endif
  514.     switch (c = getinsync (v))
  515.     {
  516.       default:
  517.         upderr (v, GetLocalString( &li, MSG_TRANSFER_CANCELLED ), XPRU_UPLOAD);
  518.         bfclose (v);
  519.         return ERROR;
  520.       case ZSKIP:                /* Receiver changed its mind and wants to skip the file */
  521.         return c;
  522.       case ZACK:                /* ACK at end of frame; resume sending data */
  523.         break;
  524.       case ZRPOS:                /* An error; resend data from last good point */
  525. #ifdef KDEBUG
  526. KPrintF("zgetinsync returned ZRPOS: Strtpos=%ld Rxpos=%ld Txpos=%ld\n", (long) v->Strtpos, (long) v->Rxpos, (long) v->Txpos);
  527. #endif
  528.         blklen >>= 2;
  529.         if (blklen < MINBLOCK)
  530.           blklen = MINBLOCK;
  531.         if (goodneeded < MAXGOODNEEDED)
  532.           goodneeded <<= 1;
  533. #ifdef KDEBUG
  534. KPrintF("bumping goodneeded/blklen: maxblklen=%ld  goodneeded=%ld\nzgetinsync ZRPOS:blklen=%ld  goodbytes=%ld\n",
  535.         (long) maxblklen, (long) goodneeded, (long) blklen, (long) goodbytes);
  536. #endif
  537.         if (v->NoMask) v->xpru.xpru_updatemask = XPRU_ERRORS;
  538.         else v->xpru.xpru_updatemask = XPRU_UPLOAD | XPRU_ERRORS;
  539.         ++v->xpru.xpru_errors;
  540.         (*v->io.xpr_update) (&v->xpru);
  541.         break;
  542.       case ZRINIT:
  543.         updmsg (v, GetLocalString( &li, MSG_DONE ), XPRU_UPLOAD);
  544.         return OK;
  545.     }
  546.   } /* while charavail */
  547.  
  548.   /* Transmit ZDATA frame header */
  549.   framelen = v->Rxbuflen;
  550.   stohdr (v, v->Txpos);
  551.   zsbhdr (v, ZDATA);
  552.  
  553.   /* Keep sending data packets until finished or interrupted */
  554.   do
  555.   {
  556.     /* Read next chunk of file data */
  557.     c = bfread (v, v->Pktbuf, (long) blklen);
  558.  
  559.     /* Figure out how to handle this data packet */
  560.     if (c < blklen)
  561.       e = ZCRCE;                /* If end of file, this is last data packet */
  562.     else if (v->Rxbuflen && (framelen -= c) <= 0)
  563.       e = ZCRCW;                /* If end of frame, ask for ACK */
  564.     else
  565.       e = ZCRCG;                /* Else tell receiver to expect more data packets */
  566.  
  567.     zsdata (v, c, e);                /* Send the packet */
  568.     sendbuf (v);
  569.  
  570.     /* Update comm program status display */
  571.     if (v->NoMask) 
  572.       v->xpru.xpru_updatemask = XPRU_BLOCKS | XPRU_BLOCKSIZE | XPRU_BYTES
  573.         | XPRU_EXPECTTIME | XPRU_ELAPSEDTIME | XPRU_DATARATE
  574.         | XPRU_BLOCKCHECK;
  575.     else 
  576.       v->xpru.xpru_updatemask = XPRU_UPLOAD | XPRU_BLOCKS | XPRU_BLOCKSIZE | XPRU_BYTES
  577.         | XPRU_EXPECTTIME | XPRU_ELAPSEDTIME | XPRU_DATARATE
  578.         | XPRU_BLOCKCHECK;
  579.     ++v->xpru.xpru_blocks;
  580.     v->xpru.xpru_blocksize = c;
  581.     v->xpru.xpru_blockcheck = v->Crc32t ? "CRC-32" : "CRC-16";
  582.     v->xpru.xpru_bytes = v->Txpos += c;
  583.     update_rate (v);
  584.     (*v->io.xpr_update) (&v->xpru);
  585.  
  586. #ifdef KDEBUG
  587. KPrintF("sent: maxblklen=%ld  goodneeded=%ld Sent=%ld   Pos:%ld\n         blklen=%ld            goodbytes=%ld\n",
  588.         (long) maxblklen, (long) goodneeded, (long) c, (long) v->Txpos, (long) blklen, (long) goodbytes);
  589. #endif
  590.     /*
  591.        * If we've been sending smaller than normal packets, see if it's
  592.        * time to bump the packet size up a notch yet
  593.      */
  594.     if (blklen < maxblklen && (goodbytes += c) >= goodneeded)
  595.     {
  596.       blklen <<= 1;
  597.       if (blklen > maxblklen)
  598.         blklen = maxblklen;
  599. #ifdef KDEBUG
  600. KPrintF("bump: maxblklen=%ld  goodneeded=%ld Sent=%ld   Pos:%ld\nbump to: blklen=%ld            goodbytes=%ld\n",
  601.         (long) maxblklen, (long) goodneeded, (long) c, (long) v->Txpos, (long) blklen, (long) goodbytes);
  602. #endif
  603.       goodbytes = 0;
  604. #ifdef DEBUGLOG
  605.       xprsprintf (v->Msgbuf, "Bumping packet size to %ld at %ld\n",
  606.                   (long) blklen, v->Txpos);
  607.       dlog (v, v->Msgbuf);
  608.       D (DEBUGINFO);
  609. #endif
  610.     }
  611.  
  612.     /* Give comm program its timeslice if it needs one */
  613.     if (v->io.xpr_chkmisc)
  614.       (*v->io.xpr_chkmisc) ();
  615.     /* Check for abort from comm program */
  616.     if (v->io.xpr_chkabort && (*v->io.xpr_chkabort) ())
  617.       goto aborted;
  618.     /* If this was last packet in frame, go wait for ACK from receiver */
  619.     if (e == ZCRCW)
  620.     {
  621. #ifdef KDEBUG
  622. KPrintF("last packet in frame, waiting for ACK\n");
  623. #endif
  624.       goto waitack;
  625.     }
  626.     /*
  627.        * Check if receiver trying to interrupt us; look for incoming packet
  628.        * while discarding line noise
  629.      */
  630. #ifdef KDEBUG
  631. KPrintF("Looking for interrupt ---");
  632. #endif
  633.     while (char_avail (v))
  634.     {
  635. #ifdef KDEBUG
  636. KPrintF("char_avail\n");
  637. #endif
  638.  
  639.       switch (readock (v, 1))
  640.       {
  641.       case CAN:
  642.       case RCDO:
  643.       case ZPAD:
  644.         /* Interruption detected; stop sending and process complaint */
  645. #ifdef KDEBUG
  646. KPrintF("Got ZPAD, send interrupted\n");
  647. #endif
  648. #ifdef DEBUGLOG
  649.         dlog (v, "--- Interrupted send\n");
  650.         D (DEBUGINFO);
  651. #endif
  652.         zsdata (v, 0, ZCRCE);
  653.         sendbuf (v);
  654.         goto waitack;
  655.       }
  656.     }
  657. #ifdef KDEBUG
  658. KPrintF("No char_avail\n");
  659. #endif
  660.  
  661.   } while (e == ZCRCG);                /* If no interruption, keep sending data packets */
  662.  
  663.   /* Done sending file data; send EOF and wait for receiver to acknowledge */
  664.   while (TRUE)
  665.   {
  666.     updmsg (v, GetLocalString( &li, MSG_SENDING_EOF ), XPRU_UPLOAD);
  667.     stohdr (v, v->Txpos);
  668.     zsbhdr (v, ZEOF);
  669.     sendbuf (v);
  670.     switch (c = getinsync (v))
  671.     {
  672.     case ZACK:
  673.       continue;
  674.     case ZRPOS:
  675.       goto somemore;
  676.     case ZRINIT:
  677.       updmsg (v, GetLocalString( &li, MSG_EOF_ACKNOWLEDGED ), XPRU_UPLOAD);
  678.       ++v->Starttime.tv_secs;
  679.       update_rate (v);
  680.       v->xpru.xpru_updatemask = XPRU_UPLOAD | XPRU_EXPECTTIME | 
  681.                                 XPRU_ELAPSEDTIME | XPRU_DATARATE;
  682.       (*v->io.xpr_update) (&v->xpru);
  683.       return OK;
  684.     case ZSKIP:
  685.       return c;
  686.     default:
  687.   aborted:
  688.       upderr (v, GetLocalString( &li, MSG_TRANSFER_CANCELLED ), XPRU_UPLOAD);
  689.       bfclose (v);
  690.       return ERROR;
  691.     }
  692.   }
  693. }                                /* End of short zsendfdata() */
  694.  
  695. /**********************************************************
  696.  *      short getinsync(struct Vars *v)
  697.  *
  698.  * Respond to receiver's complaint, get back in sync with
  699.  * receiver
  700.  **********************************************************/
  701. short
  702. getinsync (struct Vars *v)
  703. {
  704.   short c;
  705.  
  706.   while (TRUE)
  707.   {
  708. #ifdef DEBUGLOG
  709.     dlog (v, "--- At getinsync\n");
  710.     D (DEBUGINFO);
  711. #endif
  712.     c = zgethdr (v);
  713.     if (v->io.xpr_sflush)
  714.       (*v->io.xpr_sflush) ();
  715.     v->Modemcount = 0;
  716.     switch (c)
  717.     {
  718.     case ZCAN:
  719.     case ZABORT:
  720.     case ZFIN:
  721.     case RCDO:
  722.     case TIMEOUT:
  723.       upderr (v, v->Msgbuf, XPRU_UPLOAD);
  724.       return ERROR;
  725.     case ZRPOS:
  726. #ifdef KDEBUG
  727. KPrintF("in GIS ZRPOS:Strtpos=%ld Rxpos=%ld Txpos=%ld\n",
  728.    (long) v->Strtpos, (long) v->Rxpos, (long) v->Txpos);
  729. #endif
  730.       bfseek (v, v->Rxpos);
  731.       v->Txpos = v->Rxpos;
  732.       xprsprintf (v->Msgbuf, "%s %ld", GetLocalString( &li, MSG_RESENDING_FROM ), v->Txpos);
  733.       upderr (v, v->Msgbuf, XPRU_UPLOAD);
  734. #ifdef KDEBUG
  735. KPrintF("repositioning:Strtpos=%ld Rxpos=%ld Txpos=%ld\n",
  736.    (long) v->Strtpos, (long) v->Rxpos, (long) v->Txpos);
  737. #endif
  738.       return c;
  739.     case ZSKIP:
  740.       upderr (v, GetLocalString( &li, MSG_SKIP_COMMAND_RECEIVED ), XPRU_UPLOAD);
  741.       /* fallthrough... */
  742.     case ZRINIT:
  743.       bfclose (v);
  744.       /* fallthrough... */
  745.     case ZACK:
  746.       return c;
  747.     default:
  748.       zsbhdr (v, ZNAK);
  749.       sendbuf (v);
  750.       continue;
  751.     }
  752.   }
  753. }                                /* End of short getinsync() */
  754.  
  755. /**********************************************************
  756.  *      void saybibi(struct Vars *v)
  757.  *
  758.  * End of batch transmission; disengage cleanly from receiver
  759.  **********************************************************/
  760. void
  761. saybibi (struct Vars *v)
  762. {
  763. #ifdef DEBUGLOG
  764.   D (DEBUGINFO);
  765. #endif
  766.  
  767.   while (TRUE)
  768.   {
  769.     stohdr (v, 0L);
  770.     zsbhdr (v, ZFIN);
  771.     sendbuf (v);
  772.     switch (zgethdr (v))
  773.     {
  774.     case ZFIN:
  775.       sendline (v, 'O');
  776.       sendline (v, 'O');
  777.       sendbuf (v);
  778.       /* fallthrough... */
  779.     case ZCAN:
  780.     case RCDO:
  781.     case TIMEOUT:
  782.       return;
  783.     }
  784.   }
  785. }                                /* End of void saybibi() */
  786. /* End of Send.c source */
  787.